package wml.clipstore.storage.clips;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;

import wml.clipstore.base.Entity;
import wml.clipstore.map.MapManager;
import CLIPSJNI.InstanceAddressValue;
import CLIPSJNI.PrimitiveValue;

public class InstanceWrapper {

	void loadEntity(ObjectAddress address, HashMap<String, Object> getted,
			Stack<ObjectAddress> toGet) throws InstantiationException,
			IllegalAccessException, ClassNotFoundException {
		Entity entity = (Entity) address.getObject();
		InstanceAddressValue addr = address.getAddress();
		List<Field> fields = MapManager.getInstance().getStoredFields(
				entity.getClass());
		for (Field f : fields) {
			PrimitiveValue pv = addr.directGetSlot("f_" + f.getName());
			f.setAccessible(true);
			if (pv.getClass().equals(InstanceAddressValue.class)) {
				InstanceAddressValue inv = (InstanceAddressValue) pv;
				Object value = getted.get(inv.toString());
				if (value == null) {
					value = Class
							.forName(inv.directGetSlot("class").toString())
							.newInstance();
					getted.put(inv.toString(), value);
					toGet.push(new ObjectAddress(inv, value));
				}
				f.set(entity, value);
			} else {
				try {
					String v = pv.stringValue();
					f.set(entity, getValue(v));
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

	void loadCollecion(ObjectAddress address, HashMap<String, Object> getted,
			Stack<ObjectAddress> toGet) {
		@SuppressWarnings("unchecked")
		Collection<Object> collection = (Collection<Object>) address
				.getObject();
		InstanceAddressValue addr = address.getAddress();
		try {
			List<?> list = addr.directGetSlot("items").multifieldValue();
			for (int i = 0; i < list.size(); i++) {
				Object pv = list.get(i);
				if (pv.getClass().equals(InstanceAddressValue.class)) {
					InstanceAddressValue inv = (InstanceAddressValue) pv;
					Object value = getted.get(inv.toString());
					if (value == null) {
						value = Class.forName(
								inv.directGetSlot("class").toString())
								.newInstance();
						getted.put(inv.toString(), value);
						toGet.push(new ObjectAddress(inv, value));
					}
					collection.add(value);
				} else {
					String v = pv.toString();
					collection.add(getValue(v));
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private Object getValue(String v) throws IllegalArgumentException,
			SecurityException, InstantiationException, IllegalAccessException,
			InvocationTargetException, NoSuchMethodException,
			ClassNotFoundException {
		int index = v.lastIndexOf('@');
		StringBuilder sv = new StringBuilder(v);
		String clazz = sv.substring(index + 1);
		Object value = null;
		if (!clazz.equals("null")) {
			String initargs = sv.substring(0, index);
			value = Class.forName(clazz).getConstructor(String.class)
					.newInstance(initargs);
		}
		return value;
	}
}
